package org.young.common.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
public class JsonUtil {

	private static final ObjectMapper MAPPER;

	static {
		MAPPER = new ObjectMapper();
		SimpleModule module = new SimpleModule();
		module.addSerializer(LocalDate.class, new LocalDateSerializer());
		module.addSerializer(LocalTime.class, new LocalTimeSerializer());
		module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
		MAPPER.registerModule(module);
	}

	/**
	 * 将对象转换成json字符串。
	 * <p>
	 * Title: pojoToJson
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 *
	 * @param data
	 * @return
	 */
	public static String objectToJson(Object data) {
		try {
			if (data == null) {
				log.error("data is null");
				return null;
			}
			String string = MAPPER.writeValueAsString(data);
			return string;
		} catch (JsonProcessingException e) {
			log.error("objectToJson error: ", e);
		}
		return null;
	}

	/**
	 * 将json结果集转化为对象
	 *
	 * @param jsonData json数据
	 * @return
	 */
	public static <T> T jsonToPojo(String jsonData, Class<T> beanType) {
		try {
			if (StringUtils.isBlank(jsonData)) {
				log.error("jsonData is null");
				return null;
			}
			T t = MAPPER.readValue(jsonData, beanType);
			return t;
		} catch (Exception e) {
			log.error("jsonToPojo error: ", e);
		}
		return null;
	}

	/**
	 * 将json数据转换成pojo对象list
	 * <p>
	 * Title: jsonToList
	 * </p>
	 * <p>
	 * Description:
	 * </p>
	 *
	 * @param jsonData
	 * @param beanType
	 * @return
	 */
	public static <T> List<T> jsonToList(String jsonData, Class<T> beanType) {
		try {
			if (StringUtils.isBlank(jsonData)) {
				log.error("jsonData is null");
				return null;
			}
			JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType);
			List<T> list = MAPPER.readValue(jsonData, javaType);
			return list;
		} catch (Exception e) {
			log.error("jsonToList error: ", e);
		}
		return null;
	}

	/**
	 * 将json结果集转化为JsonNode
	 *
	 * @param jsonData json数据
	 * @return
	 */
	public static JsonNode jsonToNode(String jsonData) {
		try {
			if (StringUtils.isBlank(jsonData)) {
				log.error("jsonData is null");
				return null;
			}
			JsonNode node = MAPPER.readTree(jsonData);
			return node;
		} catch (Exception e) {
			log.error("jsonToNode error: ", e);
		}
		return null;
	}
	//    /**
	//     * json字符串转对象
	//     *
	//     * @param jsonData
	//     * @param typeReference
	//     * @return
	//     */
	//    public static <T> T jsonToObj(String jsonData, TypeReference<T> typeReference) {
	//        try {
	//            if (StringUtils.isBlank(jsonData)) {
	//                log.error("jsonData is null");
	//                return null;
	//            }
	//            T t = MAPPER.readValue(jsonData, typeReference);
	//            return t;
	//        } catch (IOException e) {
	//            log.error("jsonToObj error: ", e);
	//        }
	//        return null;
	//    }

	public static class LocalDateSerializer extends JsonSerializer<LocalDate> {

		private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

		@Override
		public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider)
				throws IOException, JsonProcessingException {
			jgen.writeString(dateFormatter.format(value));
		}
	}

	public static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {

		private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		@Override
		public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider)
				throws IOException, JsonProcessingException {
			jgen.writeString(dateTimeFormatter.format(value));
		}
	}

	public static class LocalTimeSerializer extends JsonSerializer<LocalTime> {

		private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");

		@Override
		public void serialize(LocalTime value, JsonGenerator jgen, SerializerProvider provider)
				throws IOException, JsonProcessingException {
			jgen.writeString(timeFormatter.format(value));
		}
	}

	public static class LocalDateDeserializer extends JsonDeserializer<LocalDate> {

		private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

		@Override
		public LocalDate deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
			if (jsonParser != null && StringUtils.isNotEmpty(jsonParser.getText())) {
				return LocalDate.parse(jsonParser.getText(), dateFormatter);
			}
			return null;
		}
	}

	public static class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {

		private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

		@Override
		public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
			if (jsonParser != null && StringUtils.isNotEmpty(jsonParser.getText())) {
				return LocalDateTime.parse(jsonParser.getText(), dateTimeFormatter);
			}
			return null;
		}
	}

	public static class LocalTimeDeserializer extends JsonDeserializer<LocalTime> {

		private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");

		@Override
		public LocalTime deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException {
			if (jsonParser != null && StringUtils.isNotEmpty(jsonParser.getText())) {
				return LocalTime.parse(jsonParser.getText(), timeFormatter);
			}
			return null;
		}
	}
}
